﻿SmitearWebGL.Core.Structure.SList = Class.extend(
{
	/******** constructor ********/
	
	init : function()
	{
		this._registClass( "SmitearWebGL.Core.Structure.SList" );
		
		/******** private property ********/
		
		this._size = 0;
		this._head = new SmitearWebGL.Core.Structure.SList.Entry();
		this._tail = new SmitearWebGL.Core.Structure.SList.Entry();
		this._head.next = this._tail;
		this._tail.pre = this._head;
		this.iterator = new SmitearWebGL.Core.Structure.SList.Iterator( this );
	}
	,
	
	/******** public method ********/
	
	tail : function()
	{
		return this._tail.pre;
	}
	,
	head : function()
	{
		return this._head.next;
	}
	,
	size : function()
	{
		return this._size;
	}
	,
	clear : function()
	{
		var i = 0;
		var p = this._head.next;
		for( ; i < this._size; ++ i )
		{
			p.next = null;
			p.pre = null;
			p.data = null;
		}
		
		this._head.next = this._tail;
		this._tail.pre = this._head;
		this._size = 0;
	}
	,
	getNode : function( idx )
	{
		var pos = - 1;
		var p = this._head
		while ( p != null && pos < idx )
		{
			p = p.next;
			pos ++ ;
		}
		return p;
	}
	,
	get : function( idx )
	{
		return this.getNode( idx ).data;
	}
	,
	push : function( data )
	{
		return this.insert( this._size, data );
	}
	,
	insert : function( idx, data )
	{
		idx = idx > this._size ? this._size : idx;
		idx = idx < 0 ? 0 : idx;
		
		var node = new SmitearWebGL.Core.Structure.SList.Entry();
		node.data = data;
		
		if ( idx == 0 )
		{
			node.next = this._head.next;
			node.pre = this._head;
			node.next.pre = node;
			node.pre.next = node;
		}
		else if ( idx == this._size )
		{
			node.next = this._tail;
			node.pre = this._tail.pre;
			node.next.pre = node;
			node.pre.next = node;
		}
		else
		{
			var p = this.getNode( idx - 1 );
			node.next = p.next;
			node.pre = p;
			node.next.pre = node;
			node.pre.next = node;
		}
		
		return ++ this._size;
	}
	,
	splice : function( idx )
	{
		idx = idx > this._size ? this._size : idx;
		idx = idx < 0 ? 0 : idx;
		
		var node = this.getNode( idx );
		node.next.pre = node.pre;
		node.pre.next = node.next;
		
		var data = node.data;
		
		node.data = null;
		node.next = null;
		node.pre = null;
		
		-- this._size;
		
		return data;
	}
	,
	shift : function()
	{
		return this.splice( 0 );
	}
	,
	pop : function()
	{
		return this.splice( this._size - 1 );
	}
	,
	swap : function( a, b )
	{
		var av = this.getNode( a );
		var bv = this.getNode( b );
		var tmp = av.data;
		av.data = bv.data;
		bv.data = tmp;
	}
}
);

SmitearWebGL.Core.Structure.SList.Entry = Class.extend(
{
	/******** constructor ********/
	
	init : function()
	{
		this._registClass( "SmitearWebGL.Core.Structure.SList.Entry" );
		
		this.next = null;
		this.pre = null;
		this.data = null;
	}
}
);

SmitearWebGL.Core.Structure.SList.Iterator = Class.extend(
{
	/******** constructor ********/
	
	init : function( list )
	{
		this._registClass( "SmitearWebGL.Core.Structure.SList.Iterator" );
		
		this._list = list;
		this.begin();
	}
	,
	
	/******** public method ********/
	
	hasNext : function()
	{
		return ( this._cousor.next.next != null );
	}
	,
	hasPre : function()
	{
		return ( this._cousor.pre.pre != null );
	}
	,
	next : function()
	{
		this._cousor = this._cousor.next;
	}
	,
	begin : function()
	{
		this._cousor = this._list.head();
	}
	,
	end : function()
	{
		return this._cousor != this._list._tail;
	}
	,
	data : function()
	{
		return this._cousor.data;
	}
}
);